package com.atguigu.gmall.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.cart.client.CartFeignClient;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.config.DeadLetterMqConfig;
import com.atguigu.gmall.order.mapper.CartInfoMapper;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderService;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    OrderDetailMapper orderDetailMapper;

    @Autowired
    CartFeignClient cartFeignClient;

    @Autowired
    ProductFeignClient productFeignClient;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    OrderInfoMapper orderInfoMapper;

    @Autowired
    RabbitService rabbitService;

    @Autowired
    CartInfoMapper cartInfoMapper;

    @Value("${ware.url}")
    String wareUrl;

    @Override
    public Long submitOrder(OrderInfo orderInfo) {
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        StringBuffer stringBuffer = new StringBuffer();
        orderDetailList.forEach(orderDetail -> {
            BigDecimal price = productFeignClient.getPrice(orderDetail.getSkuId());
            orderDetail.setOrderPrice(price);
            stringBuffer.append(orderDetail.getSkuName());
        });
        orderInfo.sumTotalAmount();
        //订单描述
        if (stringBuffer != null && stringBuffer.length() > 100){
            orderInfo.setTradeBody(stringBuffer.toString().substring(0, 100));
        }else {
            orderInfo.setTradeBody(stringBuffer.toString());
        }
        //订单编号
        String outTradeNo = "ATGUIGU"+System.currentTimeMillis()+new Random().nextInt(1000);
        orderInfo.setOutTradeNo(outTradeNo);
        //创建时间
        Calendar calendar = Calendar.getInstance();
        orderInfo.setCreateTime(calendar.getTime());
        //失效时间
        calendar.add(Calendar.HOUR,2);
        orderInfo.setExpireTime(calendar.getTime());
        //进度状态
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        //数据库
        orderInfoMapper.insert(orderInfo);
        List<OrderDetail> orderDetailList1 = orderInfo.getOrderDetailList();
        List<String> skuIds = new ArrayList<>();
        orderDetailList1.forEach(orderDetail -> {
            orderDetail.setOrderId(orderInfo.getId());
            skuIds.add(orderDetail.getSkuId().toString());
            //删数据库
            cartInfoMapper.delete(new QueryWrapper<CartInfo>().eq("sku_id",orderDetail.getSkuId().toString()));
            orderDetailMapper.insert(orderDetail);
        });
        String cacheH = RedisConst.USER_KEY_PREFIX+orderInfo.getUserId()+RedisConst.USER_CART_KEY_SUFFIX;
        redisTemplate.opsForHash().delete(cacheH,skuIds.toArray());
        //取消订单
        rabbitService.sendDeadLetterMessage(orderInfo.getId(), DeadLetterMqConfig.exchange_dead,DeadLetterMqConfig.routing_dead_1,300);
        return orderInfo.getId();
    }

    @Override
    public boolean hasStock(Long skuId, Integer skuNum) {
        String url = wareUrl + "/hasStock?skuId="+skuId+"&num="+skuNum;
        return "1".equals(HttpClientUtil.doGet(url));
    }

    @Override
    public void cancelOrder(Long orderId) {
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        if (orderInfo != null){
            if (orderInfo.getOrderStatus().equals(OrderStatus.UNPAID.name())) {
                orderInfo.setOrderStatus(OrderStatus.CLOSED.name());
                orderInfoMapper.updateById(orderInfo);
                System.out.println("订单取消成功 "+ new Date());
            }
        }
    }

    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        orderInfo.setOrderDetailList(orderDetailMapper.selectList(new QueryWrapper<OrderDetail>().eq("order_id",orderId)));
        return orderInfo;
    }

    @Override
    public void updateOrderStatus(Long orderId, ProcessStatus processStatus) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setId(orderId);
        orderInfo.setOrderStatus(processStatus.getOrderStatus().name());
        orderInfo.setProcessStatus(processStatus.name());
        orderInfoMapper.updateById(orderInfo);
    }

    @Override
    public void sendOrderStatus(Long orderId) {
        updateOrderStatus(orderId, ProcessStatus.NOTIFIED_WARE);
        OrderInfo orderInfo = getOrderInfo(orderId);
        Map<String,Object> resultMap = initWareOrder(orderInfo);
        rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_WARE_STOCK,MqConst.ROUTING_WARE_STOCK, JSONObject.toJSONString(resultMap));
    }

    @Override
    public List<Map> orderSplit(Long orderId, String wareSkuMap) {
        List<Map> listMap = JSONObject.parseArray(wareSkuMap, Map.class);
        OrderInfo orderInfo = getOrderInfo(orderId);

        List<Map> skuIds1 = listMap.stream().map(map -> {
            //遍历仓库   每一个仓库就是map
            //一个仓库是一张订单
            //子订单  数据来原于父订单
            OrderInfo subOrderInfo = new OrderInfo();
            BeanUtils.copyProperties(orderInfo, subOrderInfo);
            //1) 设置子订单的ID为null
            subOrderInfo.setId(null);
            //2) 设置父ID
            subOrderInfo.setParentOrderId(orderInfo.getId());
            //3)记录子订单所在仓库
            subOrderInfo.setWareId(String.valueOf(map.get("wareId")));
            //保存子订单的订单详情
            List<String> skuIds = (List<String>) map.get("skuIds");
            //一个仓库有多个子订单详情集合
            List<OrderDetail> subOrderDetailList = new ArrayList<>();
            for (String skuId : skuIds) {
                List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
                for (OrderDetail detail : orderDetailList) {
                    if (detail.getSkuId().toString().equals(skuId)) {
                        subOrderDetailList.add(detail);
                        break;
                    }
                }
            }
            //3)设置子订单的订单详情的引用
            subOrderInfo.setOrderDetailList(subOrderDetailList);
            //计算总金额
            subOrderInfo.sumTotalAmount();
            //保存子订单
            orderInfoMapper.insert(subOrderInfo);
            //更新当前子订单对应的多个订单详情（设置外键）
            subOrderInfo.getOrderDetailList().forEach(orderDetail -> {
                orderDetail.setOrderId(subOrderInfo.getId());
                orderDetailMapper.updateById(orderDetail);
            });
            return initWareOrder(subOrderInfo);
        }).collect(Collectors.toList());
        return skuIds1;
    }

    private Map<String, Object> initWareOrder(OrderInfo orderInfo) {
        Map<String,Object> resultMap = new HashMap<>();
        resultMap.put("orderId",orderInfo.getId());
        resultMap.put("consignee",orderInfo.getConsignee());
        resultMap.put("consigneeTel",orderInfo.getConsigneeTel());
        resultMap.put("orderComment",orderInfo.getOrderComment());
        resultMap.put("orderBody",orderInfo.getTradeBody());
        resultMap.put("deliveryAddress",orderInfo.getDeliveryAddress());
        resultMap.put("paymentWay","ONLINE".equals(orderInfo.getPaymentWay())?"2":"1");
        List<Map> details = orderInfo.getOrderDetailList().stream().map(orderDetail -> {
            Map map = new HashMap();
            map.put("skuId",orderDetail.getSkuId());
            map.put("skuName",orderDetail.getSkuName());
            map.put("skuNum",orderDetail.getSkuNum());
            return map;
        }).collect(Collectors.toList());
        resultMap.put("details",details);
        //传入仓库ID
        resultMap.put("wareId",orderInfo.getWareId());
        return resultMap;
    }
}
